package cn.shop.merchant.service;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.ContentType;
import cn.hutool.http.HttpUtil;
import cn.shop.merchant.mapper.gametemplate.GatewaySecretMapper;
import cn.shop.merchant.model.gameconfig.GamePartition;
import cn.shop.merchant.model.gameconfig.GatewaySecret;
import cn.shop.merchant.req.GatewaySecretQueryReq;
import cn.shop.utils.ApiCode;
import cn.shop.utils.ApiResult;
import cn.shop.utils.PageUtil;
import cn.shop.utils.Putif;
import cn.shop.utils.exception.ServiceException;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

import java.util.Map;

@Service
public class GatewaySecretService extends BaseServiceImpl<GatewaySecretMapper, GatewaySecret> {

    private static final Logger LOG = LoggerFactory.getLogger(GatewaySecretService.class);

    @Resource
    private ObjectMapper objectMapper;
    @Resource
    private GamePartitionService partitionService;

    public Map<String, Object> list(long uid, GatewaySecretQueryReq req) {
        Page<GatewaySecret> page = Page.of(req.getCurrent(), req.getSize());
        page = page(page, Wrappers.<GatewaySecret>lambdaQuery()
                .eq(GatewaySecret::getUid, uid)
                .eq(notBlank.test(req.getIp()), GatewaySecret::getIp, req.getIp())
                .orderByDesc(GatewaySecret::getId));
        return PageUtil.formatPage(page, this::format);
    }

    @Transactional(rollbackFor = Exception.class)
    public boolean updateSecret(GatewaySecret secret) {
        String newSecret = IdUtil.simpleUUID().toUpperCase();
        boolean success = update(null, Wrappers.<GatewaySecret>lambdaUpdate()
                .set(GatewaySecret::getSecret, newSecret)
                .eq(GatewaySecret::getId, secret.getId()));
        if (success) {
            GamePartition partition = partitionService.getOne(Wrappers.<GamePartition>lambdaQuery()
                    .eq(GamePartition::getUid, secret.getUid())
                    .eq(GamePartition::getIp, secret.getIp()), false);
            String json = "";
            try {
                json = HttpUtil.createPost("http://" + secret.getIp() +
                                ":" + partition.getPort() + "/gateway/api/secret")
                        .header("secret", secret.getSecret())
                        .contentType(ContentType.TEXT_PLAIN.getValue())
                        .body(newSecret)
                        .execute()
                        .body();
            } catch (Exception e) {
                LOG.warn("通讯失败", e);
                throw new ServiceException("通讯失败");
            }
            if (json == null) {
                return false;
            }
            ApiResult<Object> result = null;
            try {
                result = objectMapper.readValue(json , new TypeReference<ApiResult<Object>>() {});
            } catch (JsonProcessingException e) {
                LOG.warn("json解析错误:", e);
                throw new ServiceException("系统错误");
            }
            if (result == null || result.getCode() != ApiCode.SUCCESS) {
                throw new ServiceException("系统错误");
            }
        }
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    public boolean deleteSecret(long id, long uid) {
        return remove(Wrappers.<GatewaySecret>lambdaQuery().eq(GatewaySecret::getId, id).eq(GatewaySecret::getUid, uid));
    }

    public GatewaySecret get(long id, long uid) {
        return getOne(Wrappers.<GatewaySecret>lambdaQuery()
                .eq(GatewaySecret::getId, id)
                .eq(GatewaySecret::getUid, uid));
    }

    public GatewaySecret getByIp(long uid, String ip) {
        return getOne(Wrappers.<GatewaySecret>lambdaQuery()
                .eq(GatewaySecret::getIp, ip)
                .eq(GatewaySecret::getUid, uid));
    }

    private Map<String, Object> format(GatewaySecret secret) {
        return Putif.start()
                .anyway("ip", secret.getIp())
                .anyway("secret", secret.getSecret())
                .anyway("time", secret.getCreateTime())
                .anyway("id", secret.getId())
                .get();
    }

}
